package Siebel::Code::Analyzer::DAO;

use warnings;
use strict;
use Moose;
use Encode qw(decode);
use namespace::autoclean;
use Siebel::Code::Analyzer::Repository::Script;
use DBI qw(:sql_types);

use constant ENC => 'utf-8';

has _dbh        => ( isa => 'DBI::db',  is => 'ro', lazy_build => 1 );
has data_source => ( isa => 'Str',      is => 'ro', required   => 1 );
has max_long    => ( isa => 'Str',      is => 'ro', required   => 1 );
has data_source => ( isa => 'Str',      is => 'ro', required   => 1 );
has last_upd    => ( isa => 'Str',      is => 'ro', required   => 1 );
has repo_name   => ( isa => 'ArrayRef', is => 'ro', required   => 1 );
has skip_inactive => ( isa => 'Bool', is => 'ro', required => 1, default => 0 );
has verify_runtime =>
  ( isa => 'Bool', is => 'ro', required => 1, default => 0 );

around BUILDARGS => sub {

    my $orig     = shift;
    my $class    = shift;
    my $hash_ref = shift;

    if ( $hash_ref->{skip_inactive} eq 'true' ) {

        $hash_ref->{skip_inactive} = 1;

    }
    else {

        $hash_ref->{skip_inactive} = 0;

    }

    if ( $hash_ref->{verify_runtime} eq 'true' ) {

        $hash_ref->{verify_runtime} = 1;

    }
    else {

        $hash_ref->{verify_runtime} = 0;

    }

    return $class->$orig($hash_ref);

};

sub _build__dbh {

    die
'This method must be overrided by subclasses of Siebel::Code::Analyzer::DAO';

}

sub get_runtime_query {

    die
'This method must be overrided by subclasses of Siebel::Code::Analyzer::DAO';

}

sub get_repo_queries {

    my $self = shift;

    my $total = ( scalar( @{ $self->repo_name() } ) - 1 );

    my @bind;

    for ( my $i = 0 ; $i <= $total ; $i++ ) {

        $bind[$i] = '?';

    }

    return join( ',', @bind );

}

sub get_repo_data {

    my $self = shift;

    my $queries_ref = $self->get_repo_queries();

    my @objects;

    foreach my $sth ( @{$queries_ref} ) {

        $sth->execute();

        while ( my $row = $sth->fetchrow_arrayref() ) {

            push(
                @objects,
                Siebel::Code::Analyzer::Repository::Script->new(
                    {

                        repo_name   => decode( ENC, $row->[0] ),
                        type        => decode( ENC, $row->[1] ),
                        name        => decode( ENC, $row->[2] ),
                        script_name => decode( ENC, $row->[3] ),
                        last_upd    => decode( ENC, $row->[4] ),
                        script_code => decode( ENC, $row->[5] )

                    }
                )
            );

        }

    }

    return \@objects;

}

sub _bind_params {

    my $self        = shift;
    my $queries_ref = shift;    # array reference

    my @statements;

    foreach my $sql ( @{$queries_ref} ) {

        my $sth = $self->_dbh->prepare($sql);

        my $i = 1;

   # TODO: the process below assumes that the WHERE clause has the same sequence
   # of parameters for all queries, which is a bad thing
   # should separate the interface of adding parameters to the SQL statement
   # without actually knowing how to do it, maybe DBIx::Class would help?

        # binds the Siebel repositories names from the configuration file
        foreach my $value ( @{ $self->repo_name() } ) {

            $sth->bind_param( $i, $value, SQL_VARCHAR );
            $i++;

        }

        if ( $self->skip_inactive() ) {

            $sth->bind_param( $i, 'N', SQL_VARCHAR );
            $i++;
            $sth->bind_param( $i, 'N', SQL_VARCHAR );
            $i++;

        }

        # binds the last LAST_UPD value of each query
        $sth->bind_param( $i, $self->last_upd(), SQL_TIMESTAMP );

        push( @statements, $sth );

    }

    return \@statements;

}

sub DEMOLISH {

    my $self = shift;
    $self->_dbh->disconnect();

}

=pod

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2012 of Alceu Rodrigues de Freitas Junior, E<lt>arfreitas@cpan.org<E<gt>

This project is based on the code (SiebelOVAnalyzer) provided in the article "Memory Leaks in 
Siebel" (http://siebelunleashed.com/memory-leaks-siebel/) from Timur Vafin. 

This file is part of Siebel Code Analyzer.

Siebel Code Analyzer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Siebel Code Analyzer is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Siebel Monitoring Tools.  If not, see <http://www.gnu.org/licenses/>.

=cut

__PACKAGE__->meta->make_immutable;
1;
